package com.kira.scaffoldmvc.Listener;

import com.kira.scaffoldmvc.HeartBeat.SwitchBarrier;
import com.kira.scaffoldmvc.Mapper.ds1.DictionaryMapper;
import com.kira.scaffoldmvc.Mapper.ds1.StrategyMapper;
import com.kira.scaffoldmvc.POJO.Dictionary;
import com.kira.scaffoldmvc.POJO.Strategy;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author Kira
 * Bean初始化后方法
 * 进行二级缓存的异步加载，也就是在运行时加载
 */
@Slf4j
@Component
public class BeanRegisterListener implements ApplicationListener<ContextRefreshedEvent> {

    @Resource
    private DictionaryMapper dictionaryMapper;

    @Resource
    private StrategyMapper strategyMapper;

    @Resource
    private Map<String, SwitchBarrier> switchBarrierMap;

    @Async
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {

        log.info("二级缓存开始刷新");
        loadDictionary(event);
        loadStrategy(event);

    }

    @Async
    void loadStrategy(ContextRefreshedEvent event) {
        log.info("加载策略映射关系");
        // 获取Spring上下文 ApplicationContext 并转换为 GenericApplicationContext
        GenericApplicationContext applicationContext = (GenericApplicationContext) event.getApplicationContext();

        // 调用中台接口，获取数据并构建Map
        List<Strategy> strategies = strategyMapper.selectAll();
        //用中台字典构造Map
        Map<String, Strategy> dictionaryMap = new HashMap<>();
        for (Strategy temp : strategies) {
            dictionaryMap.put(temp.getStrategyCode(), temp);
        }

        // 4. 动态注册Map为Spring Bean（与之前逻辑相同）
        BeanDefinitionRegistry registry = applicationContext;
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
                .genericBeanDefinition(Map.class, () -> dictionaryMap);

        registry.registerBeanDefinition("strategiesMap", beanDefinitionBuilder.getBeanDefinition());

        // 5. 验证：从容器中获取注册的Map
        Map<String, Dictionary> registeredMap = applicationContext.getBean("strategiesMap", Map.class);
        log.info("动态注册的策略映射关系Bean：" + registeredMap);

        SwitchBarrier kiraSwitchBarrier1 = switchBarrierMap.get("kiraSwitchBarrier1");

        try {
            kiraSwitchBarrier1.allowCross();//放行
            Thread.sleep(20000);//休眠一段时间方便测试
        } catch (Exception e) {
            log.info("放行失败,IM告警");
        }

        log.info("策略映射关系栅栏放行");
    }


    //异步加载中台字典
    @Async
    void loadDictionary(ContextRefreshedEvent event) {
        log.info("加载中台字典");
        // 获取Spring上下文 ApplicationContext 并转换为 GenericApplicationContext
        GenericApplicationContext applicationContext = (GenericApplicationContext) event.getApplicationContext();

        // 调用中台接口，获取数据并构建Map
        List<Dictionary> dictionaries = dictionaryMapper.selectAll();
        //用中台字典构造Map
        Map<String, Dictionary> dictionaryMap = new HashMap<>();
        for (Dictionary temp : dictionaries) {
            dictionaryMap.put(temp.getCode(), temp);
        }

        // 4. 动态注册Map为Spring Bean（与之前逻辑相同）
        BeanDefinitionRegistry registry = applicationContext;
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
                .genericBeanDefinition(Map.class, () -> dictionaryMap);

        registry.registerBeanDefinition("dictionariesMap", beanDefinitionBuilder.getBeanDefinition());

        // 5. 验证：从容器中获取注册的Map
        Map<String, Dictionary> registeredMap = applicationContext.getBean("dictionariesMap", Map.class);
        log.info("动态注册的中台字典Bean：" + registeredMap);

        SwitchBarrier kiraSwitchBarrier2 = switchBarrierMap.get("kiraSwitchBarrier2");

        try {
            kiraSwitchBarrier2.allowCross();//放行
            Thread.sleep(20000);//休眠一段时间方便测试
        } catch (Exception e) {
            log.info("放行失败,IM告警");
        }

        log.info("中台字典栅栏放行");
    }


}